#include <reg51.h>

#define uchar unsigned char
//#define uint  unsigned int
#define fifo_max_size 50

uchar buf;
//// uchar Buf[]="get!\n";
//uchar device[]="{\"p\":\"12345678\",\"v\":\"1.0.0\",\"k\":\"1234\"}";
uchar idata receive_data[fifo_max_size];

sbit PIN_RXD=P3^2;  //模拟串口接收引脚定义
sbit PIN_TXD=P3^3;  //模拟串口发送引脚定义

uchar RxdOrTxd = 0;  //指示当前状态为接收还是发送
uchar RxdEnd = 0;    //接收结束标志
uchar TxdEnd = 0;    //发送结束标志

uchar heart_flag = 0;//心跳包标志0/1：第一包心跳/第一包心跳之后的所有心跳

uchar RxdBuf = 0;  //接收缓冲器
uchar TxdBuf = 0;  //发送缓冲器

typedef struct{
	uchar frame_data[fifo_max_size];
	uchar fornt;
	uchar tail;
	uchar frame_size;
}Queue;

Queue fifo_queue;

/**********************硬件串口********************************/
/*波特率为9600*/
void UART_init(void)
{
    SCON = 0x50;        //串口方式1
		PCON = 0x00;
    TMOD = 0x20;        // 定时器使用方式2自动重载
    TH1 = 0xFD;    //9600波特率对应的预设数，定时器方式2下，TH1=TL1
    TL1 = 0xFD;
		EA=1;
		ES=1;
    TR1 = 1;//开启定时器，开始产生波特率
}

/*发送一个字符*/
void UART_send_byte(uchar dat)
{
	// ES = 1;
	SBUF = dat;       //把数据放到SBUF中
	while (TI == 0);//未发送完毕就等待
	TI = 0;    //发送完毕后，要把TI重新置0
	// ES =0;
}
 
/*发送一个字符串*/
void UART_send_string(uchar *buf)
{
	while (*buf != '\0')
	{
		UART_send_byte(*buf++);
    }
}

/************************IO模拟串口***************************/
/* 串口配置函数，baud-通信波特率 */
void ConfigUART(void)
{
    TMOD &= 0xF0;   //清零T0的控制位
    TMOD |= 0x02;   //配置T0为模式2
    TH0 = 160;  //计算T0重载值256 - (11059200/12)/9600
}

/* 启动串行接收 */
void StartRXD()
{
    TL0 = 256 - ((256-TH0)>>1);  //接收启动时的T0定时为半个波特率周期
    ET0 = 1;         //使能T0中断
    TR0 = 1;         //启动T0
    RxdEnd = 0;     //清零接收结束标志
    RxdOrTxd = 0;   //设置当前状态为接收
}

/* 启动串行发送，dat-待发送字节数据 */
void StartTXD(unsigned char dat)
{
    TxdBuf = dat;    //待发送数据保存到发送缓冲器
    TL0 = TH0;       //T0计数初值为重载值
    ET0 = 1;         //使能T0中断
    TR0 = 1;         //启动T0
    PIN_TXD = 0;    //发送起始位
    TxdEnd = 0;     //清零发送结束标志
    RxdOrTxd = 1;   //设置当前状态为发送
}

void TXD_send_string(uchar *Pdata,uchar pdata_len)
{
	uchar i;
	for(i=0;i<pdata_len;i++)
	{
		StartTXD(*Pdata++);
		while(!TxdEnd);
	}
}
/************************fifo********************************/
void fifo_init(void)
{
	fifo_queue.fornt = 0;
	fifo_queue.tail = 0;
	fifo_queue.frame_size = 0;
}

uchar fifo_is_full(void)
{
	return (fifo_queue.frame_size >= fifo_max_size);
}

uchar fifo_empty(void)
{
	return (fifo_queue.frame_size == 0);
}

void fifo_clean_all(void)
{
	fifo_queue.fornt = 0;
	fifo_queue.tail = 0;
	fifo_queue.frame_size = 0;
}

uchar fifo_get_size(void)
{
	return fifo_queue.frame_size;
}

uchar fifo_append_one(uchar frame_data)
{
	if(fifo_is_full())return 0;
	fifo_queue.frame_data[fifo_queue.tail] = frame_data;
	fifo_queue.tail++;
	fifo_queue.tail %= fifo_max_size;
	fifo_queue.frame_size++;
	return 1;
}

uchar fifo_add_strings(uchar *Pdata, uchar pdata_len)
{
	uchar i;
	if(fifo_queue.frame_size + pdata_len > fifo_max_size)return 0;
	for(i = 0; i < pdata_len; i++)
	{
		fifo_queue.frame_data[fifo_queue.tail] = Pdata[pdata_len];
		fifo_queue.tail++;
		fifo_queue.tail %= fifo_max_size;
		fifo_queue.frame_size++;
	}
	return 1;
}

uchar fifo_read_strings(uchar *Pdata, uchar pdata_len)
{
	uchar i;
	uchar num = (fifo_queue.frame_size > pdata_len ? pdata_len:fifo_queue.frame_size);
	uchar j = fifo_queue.fornt;
	// UART_send_byte(j);
	for(i=0;i<num;i++){
			Pdata[i] = fifo_queue.frame_data[j];
			j++;
			j %= fifo_max_size;
	}
	return num;
}

uchar fifo_pop(uchar pdata_len)
{
	fifo_queue.fornt += pdata_len;
	fifo_queue.fornt %= fifo_max_size;
	fifo_queue.frame_size -= pdata_len;
  return pdata_len;
}

/*******************cmd_fun函数***********************/
void respond_heart(void)
{
	EA = 0;
	UART_send_byte(0x55);
	UART_send_byte(0xaa);
	UART_send_byte(0x01);
	UART_send_byte(0x00);
	UART_send_byte(0x00);
	UART_send_byte(0x01);
	if(heart_flag == 0){//发送第一包心跳回复
		UART_send_byte(0x00);
		heart_flag = 1;
		UART_send_byte(0x01);
	}
	else{//发送第一包心跳之后的多有心跳回复
		UART_send_byte(0x01);
		UART_send_byte(0x02);
	}
	EA = 1;
}

void respond_device_message(void)
{
	uchar message_string[]="{\"p\":\"N5T1Irtw\",\"v\":\"1.0.0\",\"k\":\"1002\"}";
	uchar i=0,check_sum;
	EA = 0;
	UART_send_byte(0x55);
	UART_send_byte(0xaa);
	UART_send_byte(0x01);
	UART_send_byte(0x01);//cmd
	UART_send_byte(0x00);//len_H
	UART_send_byte(0x27);//len_L
	
	check_sum = 0x28;
	
	while(message_string[i] != '\0'){
		check_sum+=message_string[i];
		UART_send_byte(message_string[i]);
		i++;
	}
	
	UART_send_byte(check_sum);
	EA = 1;
}

void respond_mesh_state(void)
{
	EA = 0;
	UART_send_byte(0x55);
	UART_send_byte(0xaa);
	UART_send_byte(0x01);
	UART_send_byte(0x02);
	UART_send_byte(0x00);
	UART_send_byte(0x00);
	UART_send_byte(0x02);
	EA = 1;
}

void request_reset(void)
{
	EA = 0;
	UART_send_byte(0x55);
	UART_send_byte(0xaa);
	UART_send_byte(0x01);
	UART_send_byte(0x03);
	UART_send_byte(0x00);
	UART_send_byte(0x00);
	UART_send_byte(0x03);
	EA = 1;
}

void respond_upload(void)
{
	EA = 0;
	UART_send_byte(0x55);
	UART_send_byte(0xaa);
	UART_send_byte(0x01);
	UART_send_byte(0x05);//cmd
	UART_send_byte(0x00);//len_H
	UART_send_byte(0x0d);//len_L
	UART_send_byte(0x10);//设备类型（大类）
	UART_send_byte(0x03);//设备类型（小类）
	UART_send_byte(0xdb);//设备数据上报命令
	UART_send_byte(0x01);//state1
	UART_send_byte(0x32);//state2
	UART_send_byte(0x00);//state3
	UART_send_byte(0x00);//state4
	UART_send_byte(0x00);//state5
	UART_send_byte(0x00);//state6
	UART_send_byte(0x00);//state7
	UART_send_byte(0x00);//state8
	UART_send_byte(0x00);//默认0x00
	UART_send_byte(0x00);//默认0x00
	UART_send_byte(0x03);//check sum
	EA = 1;
}

void respond_download(void)
{
	EA = 0;
	UART_send_byte(0x55);
	UART_send_byte(0xaa);
	UART_send_byte(0x01);
	UART_send_byte(0x06);//cmd
	UART_send_byte(0x00);//len_H
	UART_send_byte(0x00);//len_L
	UART_send_byte(0x06);//check sum
	EA = 1;
}

void delay(unsigned char xms)  // xms代表需要延时的毫秒数
{
	unsigned int x,y;
	for(x=xms;x>0;x--)
		for(y=110;y>0;y--);
}

uchar check_sum(uchar *Pdata,uchar Pdata_len)
{
	uchar i,sum=0;
	for(i=0;i<Pdata_len;i++)
	{
		sum = sum+Pdata[i];
	}
	return sum;
}

void frame_data_deal(void)
{ 
	uchar i;
	uchar len,cmd;
	if(fifo_get_size()<7)
		return;
	fifo_read_strings(receive_data,7);

	if((receive_data[0]!=0x55) || (receive_data[1]!=0xaa) || (receive_data[2]!=0x00)){
//		EA = 0;
		fifo_pop(1);
//		EA = 1;
	}
	else{
//		EA = 0;
//		EA = 1;
		len = receive_data[5];
		cmd = receive_data[3];
		if(len>46){//frame len error
//				EA = 0;
//				EA = 1;
				fifo_pop(3);
				return;
		}
		else{
			EA = 0;
			fifo_read_strings(receive_data,7+len);
			if(check_sum(receive_data,7+len-1) == receive_data[7+len-1])//sumcheck error
			{
//				EA = 0;
				fifo_pop(7+len);
				switch(cmd){
					case 0x00:{respond_heart();StartTXD('H');while(!TxdEnd);break;}//respond heart回复心跳
					case 0x01:{respond_device_message();StartTXD('M');while(!TxdEnd);break;}//respond device message将设备的信息上报给mesh模块
					case 0x02:{respond_mesh_state();StartTXD('S');while(!TxdEnd);break;}//respond device mesh state回复设备mesh状态（可以根据设备的mesh网络状态做出不同的执行动作）
					case 0x03:{request_reset();StartTXD('R');while(!TxdEnd);break;}//request reset发送重置指令
					case 0x04:{StartTXD('X');while (!TxdEnd);break;}//request ad发送需要广播的指令
					case 0x05:{respond_upload();StartTXD('U');while(!TxdEnd);break;}//respond upload上报设备的设备的各个DP点状态
					case 0x06:{respond_download();StartTXD('D');while(!TxdEnd);break;}//respond download设备接收到的控制命令（需要在此处对接收到的下发命令进行解析执行相应的操作）
					case 0x07:{StartTXD('N');while(!TxdEnd);break;}//respond notify
					case 0x08:{respond_upload();StartTXD('A');while(!TxdEnd);break;}//respond request all回复上报所有状态的请求
					default:break;
				}
				EA = 1;
			}
			else{
//				EA = 0;
				fifo_pop(3);
//				EA = 1;
			}
		}
	}
}
/*******************主程序*********************/

void main(void)
{
		uchar i;
    UART_init();
    ConfigUART();
    fifo_init();
    while(1){
        frame_data_deal();
        delay(1000);
    }
}
 
//串行中断服务函数
void serial() interrupt 4
{
	ES=0;		//暂时关闭串口中断
	RI=0;		//接收完把RI置0，等待下次接收
	buf=SBUF;	//把收到的信息从SBUF放到buf中。
//  UART_send_byte(buf);
	fifo_append_one(buf);
	ES=1;		//重新开启串口中断
}

/* T0中断服务函数，处理模拟串行发送和接收 */
void InterruptTimer0() interrupt 1
{
    static unsigned char cnt = 0; //位接收或发送计数
 
    if (RxdOrTxd)  //串行发送处理
    {
        cnt++;
        if (cnt <= 8)  //低位在先依次发送8bit数据位
        {
            PIN_TXD = TxdBuf & 0x01;
            TxdBuf >>= 1;
        }
        else if (cnt == 9)  //发送停止位
        {
            PIN_TXD = 1;
        }
        else  //发送结束
        {
            cnt = 0;     //复位bit计数器
            TR0 = 0;     //关闭T0
            TxdEnd = 1; //置发送结束标志
        }
    }
    else  //串行接收处理
    {
        if (cnt == 0)     //处理起始位
        {
            if (!PIN_RXD) //起始位为0时，清零接收缓冲器，准备接收数据位
            {
                RxdBuf = 0;
                cnt++;
            }
            else           //起始位不为0时，中止接收
            {
                TR0 = 0;  //关闭T0
            }
        }
        else if (cnt <= 8)   //处理8位数据位
        {
            RxdBuf >>= 1;    //低位在先，所以将之前接收的位向右移
            if (PIN_RXD)     //接收脚为1时，缓冲器最高位置1，
            {                  //而为0时不处理即仍保持移位后的0
                RxdBuf |= 0x80;
            }
            cnt++;
        }
        else  //停止位处理
        {
            cnt = 0;          //复位bit计数器
            TR0 = 0;          //关闭T0
            if (PIN_RXD)     //停止位为1时，方能认为数据有效
            {
                RxdEnd = 1;  //置接收结束标志
            }
        }
    }
}